Lock the JVM-args contract of the Compiler launch tasks#79
Merged
Conversation
Consumer builds need to attach the JaCoCo agent to the JVM forked by `launch*SpineCompiler` tasks to capture the coverage of the Compiler plugins executed there (see `.agents/tasks/compiler-coverage-plan.md`, Phases 0-1). The tasks already preserve consumer-supplied JVM arguments; this change turns that behavior into a supported, regression-tested contract: - `LaunchTaskJvmArgsSpec` locks in-process that the launch task is a plain `JavaExec` and consumer JVM args coexist with the defaults. - `LaunchTaskCoverageSpec` with the new `coverage-agent-test` fixture locks end-to-end that an agent attached via `jvmArgumentProviders` reaches the fork, records plugin-class execution matching the jars the fork loaded (class IDs), and survives an `UP-TO-DATE` launch. - The `LaunchSpineCompiler` KDoc now declares the fork options part of the task's public contract. - `RunnerTuning.tuneRunner()` deduplicates the TestKit runner setup shared by `PluginSpec` and the new spec. The task plan is updated with the Phase 0 findings (decision gate A: no relocation in the fat CLI, class IDs match by construction) and the Phase 1 outcome. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR formalizes and regression-tests the public contract that launch*SpineCompiler tasks remain plain JavaExec tasks whose consumer-supplied JVM fork options (e.g., -javaagent: via jvmArgumentProviders) are preserved, enabling JaCoCo/Kover to capture coverage from code executed inside the forked Compiler JVM.
Changes:
- Adds an in-process unit spec (
LaunchTaskJvmArgsSpec) and an end-to-end functional spec (LaunchTaskCoverageSpec+coverage-agent-testfixture) to lock the JVM-args/JaCoCo-agent behavior. - Documents the instrumentation/JVM-args contract in
LaunchSpineCompilerKDoc and refactors shared TestKit runner configuration intoRunnerTuning.tuneRunner(). - Updates the compiler version used by the build/test ecosystem.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| version.gradle.kts | Bumps the Compiler version used by the build/integration tests. |
| gradle-plugin/src/test/kotlin/io/spine/tools/compiler/gradle/plugin/LaunchTaskJvmArgsSpec.kt | New unit-level contract test: launch task is JavaExec and preserves consumer JVM args alongside defaults. |
| gradle-plugin/src/main/kotlin/io/spine/tools/compiler/gradle/plugin/LaunchSpineCompiler.kt | Documents JVM fork options / instrumentation as part of the task’s supported contract. |
| gradle-plugin/src/functionalTest/resources/coverage-agent-test/src/main/proto/test.proto | Minimal proto input for the new functional fixture project. |
| gradle-plugin/src/functionalTest/resources/coverage-agent-test/settings.gradle.kts | Fixture settings (plugin resolution via mavenLocal()). |
| gradle-plugin/src/functionalTest/resources/coverage-agent-test/build.gradle.kts | Fixture wiring that attaches JaCoCo agent via jvmArgumentProviders and records plugin classpath for analysis. |
| gradle-plugin/src/functionalTest/kotlin/io/spine/tools/compiler/gradle/plugin/RunnerTuning.kt | New shared helper to tune TestKit runner JVM args and environment. |
| gradle-plugin/src/functionalTest/kotlin/io/spine/tools/compiler/gradle/plugin/PluginSpec.kt | Uses tuneRunner() instead of duplicating TestKit runner setup inline. |
| gradle-plugin/src/functionalTest/kotlin/io/spine/tools/compiler/gradle/plugin/LaunchTaskCoverageSpec.kt | New functional spec verifying agent reaches the forked JVM and produces analyzable .exec data. |
| gradle-plugin/build.gradle.kts | Adds org.jacoco.core dependency for functional tests to analyze .exec output. |
| buildSrc/src/test/kotlin/io/spine/gradle/VersionGradleFileSpec.kt | Extends tests for version.gradle.kts parsing (config-managed; not reviewed here). |
| buildSrc/src/main/kotlin/kmp-module.gradle.kts | Adjusts jvmTest JUnit/logging configuration (config-managed; not reviewed here). |
| buildSrc/src/main/kotlin/io/spine/gradle/VersionGradleFile.kt | Enhances parsing to support extra.set(...) declarations (config-managed; not reviewed here). |
| buildSrc/src/main/kotlin/io/spine/dependency/local/Compiler.kt | Updates fallback compiler versions (config-managed; not reviewed here). |
| .agents/tasks/compiler-coverage-plan.md | Adds the coverage capture plan document (config-managed; not reviewed here). |
| .agents/memory/project/functional-test-fixtures.md | Adds internal guidance for authoring functional-test fixtures (config-managed; not reviewed here). |
| .agents/memory/MEMORY.md | Registers the new memory entry (config-managed; not reviewed here). |
Reflect the `org.jacoco:org.jacoco.core` test dependency added to the `functionalTest` suite of `gradle-plugin`. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Use a `##` KDoc heading for the instrumentation section, matching the repo convention, and add a usage example of attaching the JaCoCo agent. - Replace the hard cast to `DefaultGradleRunner` with a safe cast failing with an explicit message. - Assert the `.exec` file size is unchanged after an up-to-date launch, not just its existence. - Harmonize the cross-suite reference phrasing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
armiol
approved these changes
Jul 6, 2026
State explicitly that the preserved arguments are those appended via the additive `jvmArgs(...)` function or `jvmArgumentProviders`, while assigning the `jvmArgs` property (`setJvmArgs(...)`) replaces the defaults and is outside the contract. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #79 +/- ##
============================================
+ Coverage 76.51% 76.60% +0.09%
- Complexity 681 687 +6
============================================
Files 203 205 +2
Lines 3972 4018 +46
Branches 396 400 +4
============================================
+ Hits 3039 3078 +39
- Misses 807 810 +3
- Partials 126 130 +4 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Turns the JVM fork options of the
launch*SpineCompilertasks into a supported,regression-tested contract, so consumer builds can attach the JaCoCo agent to the forked
Compiler JVM and capture the coverage of the Compiler plugins executed there.
Implements Phases 0–1 of
compiler-coverage-plan.md:LaunchTaskJvmArgsSpec(gradle-plugin/src/test) — in-process lock: the launch task is aplain
JavaExec; consumer-added JVM args coexist with the task's own--add-opensdefaults.LaunchTaskCoverageSpec+ thecoverage-agent-testfixture(
gradle-plugin/src/functionalTest) — end-to-end lock: a real JaCoCo agent attached viajvmArgumentProvidersreaches the fork, records plugin-class execution whose class IDs matchthe very jars the fork loaded (JaCoCo
Analyzerreports covered lines > 0 onUnderscorePrefixRenderer), and anUP-TO-DATElaunch keeps the.execintact.The fixture doubles as the reference wiring consumers will copy.
LaunchSpineCompilerKDoc now declares the fork options part of the task's public contract.RunnerTuning.tuneRunner()deduplicates the TestKit runner setup shared withPluginSpec.Why
Code running inside the forked compiler JVM is invisible to JaCoCo/Kover, which instrument only
the
testJVM — invalidation, the two codegen modules sit at ~0% coverage despite beingexercised on every build. Phase 0 (documented in the plan) confirmed the fix needs no new API:
the fork options already survive, the fat CLI (
compiler-cli-all) relocates nothing, and consumerplugin classes reach the fork as original artifacts, so JaCoCo class IDs match by construction.
This PR locks those guarantees so a compiler upgrade cannot silently break consumer coverage
wiring (Phase 2,
validationrepo).Verification
./gradlew build dokkaGenerate— BUILD SUCCESSFUL (full check incl. the wholefunctionalTestsuite, detekt, and Dokka link resolution).spine-code-reviewAPPROVE,kotlin-engineerAPPROVE,review-docsAPPROVE WITH CHANGES — no must-fix items.Review follow-ups (non-blocking, surfaced by the reviewers)
LaunchSpineCompiler(per
documentation-tasks.mditem 1; the wiring currently lives only in the fixture).###→##for repo consistency.LaunchTaskCoverageSpecto compare.execlength,not just existence; add a comment on the internal
DefaultGradleRunnercast inRunnerTuning.kt; harmonize the cross-suite phrasing inLaunchTaskJvmArgsSpec.🤖 Generated with Claude Code